package com.three.netty.core.handler.manager;

import com.three.common.handler.MessageBaseHandler;
import com.three.common.message.base.BaseMessage;
import com.three.config.common.IConfig;
import com.three.netty.core.handler.annotation.PacketHandlerClass;
import com.three.netty.core.handler.annotation.PacketHandlerMethod;
import com.three.common.receiver.ReceiverType;
import com.three.protocol.CommandEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by mathua on 2017/6/4.
 */
@Component
public class PacketHandlerLoader implements ApplicationListener<ContextRefreshedEvent> {
    private static Logger logger = LoggerFactory.getLogger(PacketHandlerLoader.class);

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if(event.getApplicationContext().getParent() == null){
            logger.info("加载handler：————————————start————————————");
            Map<String,Object> beans = event.getApplicationContext().getBeansWithAnnotation(PacketHandlerClass.class);
            for (Object obj : beans.values()) {
                Class<?> clazz = obj.getClass();
                logger.info("加载handler class: 扫描到handler类:{}", clazz.getName());
                for (Method method : clazz.getDeclaredMethods()) {
                    PacketHandlerMethod handle = method.getAnnotation(PacketHandlerMethod.class);
                    if (handle != null) {
                        method.setAccessible(true);
                        ReceiverType[] receivers = handle.receivers();
                        Class<?>[] paramTypes = method.getParameterTypes();
                        Class<? extends BaseMessage> classOfT = (Class<? extends BaseMessage>) paramTypes[0];
                        logger.info("加载handler method: 扫描到handler method:{}, method msgId:{}, message name:{}", method.getName(), handle.msgId(), classOfT.getName());
                        for (ReceiverType receiver : receivers) {
                            if (paramTypes.length != 1) {
                                logger.error("packet handler method params error. error params number:{}, correct number is 1.", paramTypes.length);
                                return;
                            }
                            if (!paramTypes[0].getSuperclass().equals(BaseMessage.class)) {
                                logger.error("packet handler method param is not super class:{}", BaseMessage.class.getName());
                                return;
                            }
                            MessageBaseHandler messageBaseHandler = new MessageBaseHandler(obj, method, classOfT, handle.shouldVerifyIdentity());
                            if(canRegister(handle.msgId()))
                                receiver.getReceiver().register(handle.msgId(), messageBaseHandler);
                        }
                    }
                }
            }
            logger.info("加载handler：————————————end—————————————");
        }
    }

    /**
     * 判断协议是否能被当前服务注册
     * @param command
     * @return
     */
    private boolean canRegister(CommandEnum.Command command) {
        switch (command) {
            case HTTP_PROXY:
                return IConfig.chess.http.proxy_enabled;
            default:
                return true;
        }
    }
}
